import { IController, IView, INotification, ICommand } from "../Interfaces";
import { View } from "./View";
import { Observer } from "../patterns/observer/Observer";

export class Controller implements IController {

  view: IView = null;

  commandMap: Object = null;

  multitonKey: string = null;

  static MULITON_MSG: string = "Controller instance for this multiton key already constructed!";

  static instanceMap: Object = {};

  static getInstance(key: string): IController {
    if (!Controller.instanceMap[key])
      Controller.instanceMap[key] = new Controller(key);
    return Controller.instanceMap[key];
  }

  static removeController(key: string): void {
    
    delete Controller.instanceMap[key];
  }

  constructor(key: string) {

    if (Controller.instanceMap[key])
      throw Error(Controller.MULITON_MSG);
    Controller.instanceMap[key] = this;
    this.multitonKey = key;
    this.commandMap = {};
    this.initializeController();
  }

  initializeController(): void {
    this.view = View.getInstance(this.multitonKey);
  }

  executeCommand(notification: INotification): void {
    let commandClassRes: any = this.commandMap[notification.getName()];
    if (commandClassRes) {

      let command: ICommand = <ICommand>new commandClassRes();

      command.execute(notification);
    }
  }

  registerCommand(notificationName: string, commandClassRes: Function): void {
    if (!this.commandMap[notificationName])
      this.view.registerObserver(notificationName, new Observer(this.executeCommand, this));
    this.commandMap[notificationName] = commandClassRes;
  }

  removeCommand(notificationName: string): void {
    if (this.hasCommand(notificationName)) {
      this.view.removeObserver(notificationName, this);
      delete this.commandMap[notificationName];
    }
  }

  hasCommand(notificationName: string): boolean {
    return this.commandMap[notificationName] != null;
  }
}